home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / IFACE.C < prev    next >
C/C++ Source or Header  |  1997-09-06  |  23KB  |  921 lines

  1. /* IP interface control and configuration routines
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  *
  4.  * Mods by PA0GRI
  5.  */
  6. #include "global.h"
  7. #include "ctype.h"
  8. #include "commands.h"
  9. #include "mbuf.h"
  10. #include "proc.h"
  11. #ifndef MSDOS
  12. #include "iface.h"
  13. #endif
  14. #ifdef ETHER
  15. #include "enet.h"
  16. #endif
  17. #include "arp.h"
  18. #include "pktdrvr.h"
  19. #include "nr4.h"
  20. #include "mailbox.h"
  21.  
  22. #if !defined(_lint)
  23. static char rcsid[] OPTIONAL = "$Id: iface.c,v 1.25 1997/09/07 00:31:16 root Exp root $";
  24. #endif
  25.  
  26. #ifdef NETROM
  27. extern struct iface *Nr_iface;
  28. extern char Nralias[];
  29. #endif
  30.  
  31. static void showiface (struct iface * ifp);
  32. static int ifipaddr (int argc, char *argv[], void *p);
  33. static int ifipcall (int argc, char *argv[], void *p);
  34. static int iflinkadr (int argc, char *argv[], void *p);
  35. static int ifbroad (int argc, char *argv[], void *p);
  36. static int ifnetmsk (int argc, char *argv[], void *p);
  37. static int ifmtu (int argc, char *argv[], void *p);
  38. static int ifmetric (int argc, char *argv[], void *p);
  39. static int ifforw (int argc, char *argv[], void *p);
  40. static int ifencap (int argc, char *argv[], void *p);
  41. static int ifdescr (int argc, char *argv[], void *p);
  42.  
  43. #ifdef RXECHO
  44. static int ifrxecho (int argc, char *argv[], void *p);
  45. #endif
  46.  
  47.  
  48. static const char subcommands[] = "valid subcommands:\n";
  49. static const char nochangeIP[] = "Cannot change IP address !\n";
  50. static const char setIPcall[] = "Can't set IP call\n";
  51. static const char setlinkaddr[] = "Can't set link address\n";
  52. static const char encaperr[] = "Encapsulation mode '%s' unknown\n";
  53. static const char notsametype[] = "'%s not the same type!\n";
  54. static const char showfmt[] = "%-10s IP addr %s MTU %u Metric %d Link encap ";
  55. static const char notset[] = "not set\n";
  56. static const char showlink[] = "           Link addr %s";
  57. static const char showsent[] = "           sent: ip %lu tot %lu idle %s\n";
  58. static const char showrecv[] = "           recv: ip %lu tot %lu idle %s\n";
  59. static const char showdescr[] = "           descr: %s";
  60. static const char detnope[] = "Can't detach loopback or encap interface\n";
  61. static const char showflags[] = "           flags 0x%lx trace 0x%x netmask 0x%08lx broadcast %s\n";
  62. static const char showforw[] = "           output forward to %s\n";
  63.  
  64. #ifdef AX25
  65. static const char showIPcall[] = "   IP call %s";
  66. static const char showlenirtt[] = "   Paclen %d   Irtt %lu\n";
  67. static const char showbctext[] = "           BCText: %s\n";
  68. static const char showremote[] = "           Remote call %s";
  69. #ifdef AXIP
  70. static const char showremoteIP[] = "   Remote IP addr %s\n";
  71. #endif
  72. #endif
  73.  
  74. #ifdef RXECHO
  75. static const char showrxecho[] = "         rx packets echoed to %s\n";
  76. #endif
  77.  
  78.  
  79.  
  80. struct iftcp def_iftcp = {DEF_RTT, 0L, DEF_WND, DEF_MSS, 31, DEF_RETRIES, 0, 0};
  81.  
  82. /* Interface list header */
  83. struct iface *Ifaces = &Loopback;
  84.  
  85. #ifdef AXIP
  86. extern uint32 *axipaddr;    /* table of IP addresses of AX.25 interfaces */
  87. #endif
  88.  
  89.  
  90. /* Loopback pseudo-interface */
  91. struct iface Loopback =
  92. {
  93. #ifdef ENCAP
  94.     &Encap,            /* Link to next entry */
  95. #else
  96.     NULLIF,
  97. #endif
  98.     "loopback",        /* name     */
  99.     NULLCHAR,        /* description */
  100.     0x7f000001UL,        /* addr        127.0.0.1 */
  101.     0xffffffffUL,        /* broadcast    255.255.255.255 */
  102.     0xffffffffUL,        /* netmask    255.255.255.255 */
  103.     MAXINT16,        /* mtu        No limit */
  104.     1,            /* metric */
  105.     0,            /* flags    */
  106. #ifdef NETROM
  107.     0,            /* quality  */
  108. #endif
  109.     0,            /* trace    */
  110.     NULLCHAR,        /* trfile    */
  111.     NULLFILE,        /* trfp        */
  112.     -1,            /* trsock       */
  113.     NULLIF,            /* forw        */
  114. #ifdef RXECHO
  115.     NULLIF,            /* rxecho       */
  116. #endif
  117.     NULLPROC,        /* rxproc    */
  118.     NULLPROC,        /* txproc    */
  119.     NULLPROC,        /* supv        */
  120.     0,            /* dev        */
  121.     (int32 (*)(struct iface *, int, int, int32)) 0,
  122.     NULLFP ((struct iface *, int, int32)),    /* (*iostatus)  */
  123.     NULLFP ((struct iface *)),    /* (*stop)      */
  124.     NULLCHAR,        /* hwaddr    */
  125.     NULLCHAR,        /* ipcall    */
  126.     NULLCHAR,        /* rmtaddr    */
  127. #ifdef AX25
  128.     NULL,            /* ax25 protocol data */
  129.     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  130.                 /* ax25 counters */
  131. #endif /* AX25 */
  132.     &def_iftcp,        /* tcp protocol data */
  133.     NULL,            /* extension    */
  134.     CL_NONE,        /* type        */
  135.     0,            /* xdev        */
  136.     0,            /* port        */
  137.     &Iftypes[0],        /* iftype    */
  138.     NULLFP ((struct mbuf *, struct iface *, uint32, int, int, int, int)),    /* (*send)      */
  139.     NULLFP ((struct iface *, const char *, char *, int16, struct mbuf *)),    /* (*output)    */
  140.     NULLFP ((struct iface *, struct mbuf *)),    /* (*raw)       */
  141.     NULLVFP ((struct iface *)),    /* (*show)      */
  142.     NULLFP ((struct iface *, struct mbuf *)),    /* (*discard)   */
  143.     NULLFP ((struct iface *, struct mbuf *)),    /* (*echo)      */
  144.     0,            /* ipsndcnt    */
  145.     0,            /* rawsndcnt    */
  146.     0,            /* iprecvcnt    */
  147.     0,            /* rawrcvcnt    */
  148.     0,            /* lastsent    */
  149.     0,            /* lastrecv    */
  150. };
  151.  
  152.  
  153.  
  154. #ifdef ENCAP
  155. /* Encapsulation pseudo-interface */
  156. struct iface Encap =
  157. {
  158.     NULLIF,
  159.     "encap",        /* name        */
  160.     NULLCHAR,        /* description */
  161.     INADDR_ANY,        /* addr        0.0.0.0 */
  162.     0xffffffffUL,        /* broadcast    255.255.255.255 */
  163.     0xffffffffUL,        /* netmask    255.255.255.255 */
  164.     MAXINT16,        /* mtu        No limit */
  165.     1,            /* metric */
  166.     0,            /* flags    */
  167. #ifdef NETROM
  168.     0,            /* quality  */
  169. #endif
  170.     0,            /* trace    */
  171.     NULLCHAR,        /* trfile    */
  172.     NULLFILE,        /* trfp        */
  173.     -1,            /* trsock       */
  174.     NULLIF,            /* forw        */
  175. #ifdef RXECHO
  176.     NULLIF,            /* rxecho       */
  177. #endif
  178.     NULLPROC,        /* rxproc    */
  179.     NULLPROC,        /* txproc    */
  180.     NULLPROC,        /* supv        */
  181.     0,            /* dev        */
  182.     (int32 (*)(struct iface *, int, int, int32)) 0,    /* (*ioctl)     */
  183.     NULLFP ((struct iface *, int, int32)),    /* (*iostatus)  */
  184.     NULLFP ((struct iface *)),    /* (*stop)      */
  185.     NULLCHAR,        /* hwaddr    */
  186.     NULLCHAR,        /* ipcall    */
  187.     NULLCHAR,        /* rmtaddr    */
  188. #ifdef AX25
  189.     NULL,            /* ax25 protocol data */
  190.     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  191.                 /* ax25 counters */
  192. #endif /* AX25 */
  193.     &def_iftcp,        /* tcp protocol data */
  194.     NULL,            /* extension    */
  195.     CL_NONE,        /* type        */
  196.     0,            /* xdev        */
  197.     0,            /* port        */
  198.     &Iftypes[0],        /* iftype    */
  199.     ip_encap,        /* (*send)    */
  200.     NULLFP ((struct iface *, const char *, char *, int16, struct mbuf *)),    /* (*output)    */
  201.     NULLFP ((struct iface *, struct mbuf *)),    /* (*raw)       */
  202.     NULLVFP ((struct iface *)),    /* (*show)      */
  203.     NULLFP ((struct iface *, struct mbuf *)),    /* (*discard)   */
  204.     NULLFP ((struct iface *, struct mbuf *)),    /* (*echo)      */
  205.     0,            /* ipsndcnt    */
  206.     0,            /* rawsndcnt    */
  207.     0,            /* iprecvcnt    */
  208.     0,            /* rawrcvcnt    */
  209.     0,            /* lastsent    */
  210.     0,            /* lastrecv    */
  211. };
  212.  
  213. #endif /*ENCAP*/
  214.  
  215.  
  216.  
  217. #if defined(DRSI) || defined(EAGLE) || defined(PC_EC) || defined(HAPN) || defined(PC100)
  218. char Noipaddr[] = "IP address field missing, and ip address not set\n";
  219. #endif
  220.  
  221. static struct cmds Ifcmds[] =
  222. {
  223. #ifdef AX25
  224.     { "ax25",        ifax25,        0, 0, NULLCHAR },
  225. #endif
  226.     { "broadcast",        ifbroad,    0, 2, NULLCHAR },
  227.     { "description",    ifdescr,    0, 0, NULLCHAR },
  228.     { "encapsulation",    ifencap,    0, 2, NULLCHAR },
  229.     { "forward",        ifforw,        0, 2, NULLCHAR },
  230.     { "ipaddress",        ifipaddr,    0, 2, NULLCHAR },
  231.     { "ipcall",        ifipcall,    0, 2, NULLCHAR },
  232.     { "linkaddress",    iflinkadr,    0, 2, NULLCHAR },
  233.     { "metric",        ifmetric,    0, 2, NULLCHAR },
  234.     { "mtu",        ifmtu,        0, 2, NULLCHAR },
  235.     { "netmask",        ifnetmsk,    0, 2, NULLCHAR },
  236. #ifdef RXECHO    
  237.     { "rxecho",        ifrxecho,    0, 2, NULLCHAR },
  238. #endif
  239.     { "tcp",        doiftcp,    0, 0, NULLCHAR },
  240.     { NULLCHAR,        NULL,        0, 0, NULLCHAR }
  241. };
  242.  
  243.  
  244.  
  245. /* Set interface parameters */
  246. int
  247. doifconfig (int argc, char *argv[], void *p OPTIONAL)
  248. {
  249. struct iface *ifp;
  250. int i, step = 2, newargc = argc;
  251.  
  252.     if (argc < 2) {
  253.         for (ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  254.             showiface (ifp);
  255.         return 0;
  256.     }
  257.     if ((ifp = if_lookup (argv[1])) == NULLIF) {
  258.         tprintf (Badinterface, argv[1]);
  259.         return 1;
  260.     }
  261.     if (argc == 2) {
  262.         showiface (ifp);
  263.         if (ifp->show != NULLVFP ((struct iface *)))
  264.             (*ifp->show) (ifp);
  265.         return 0;
  266.     }
  267.     if (argc == 3) {
  268.         dohelper (subcommands, Ifcmds, NULLCHAR, NULLCHAR, NULLCHAR);
  269.         return 1;
  270.     }
  271.     for (i = 2; i < argc - 1; i += step) {
  272.         step = (tolower (argv[i][0]) == 't') ? 3 : 2;
  273.         (void) subcmd (Ifcmds, newargc - 1, &argv[i - 1], ifp);
  274.         newargc -= step;
  275.     }
  276.     return 0;
  277. }
  278.  
  279.  
  280.  
  281. /* Remove iface tracing to the current output socket */
  282. void 
  283. removetrace ()
  284. {
  285. struct iface *ifp;
  286.  
  287.     for (ifp = Ifaces; ifp; ifp = ifp->next)
  288.         if (ifp->trsock == Curproc->output) {
  289.             ifp->trace = 0;
  290.             /* We have to close the socket, because usesock() was called !*/
  291.             close_s (ifp->trsock);
  292.             ifp->trsock = -1;
  293.         }
  294. }
  295.  
  296.  
  297.  
  298. static int
  299. ishexaddr (char *str)
  300. {
  301. int k;
  302. int l = (int) strlen (str);
  303.  
  304.     if (l < 8 || l > 10)
  305.         return 0;
  306.     if (!strncasecmp (str, "0x", 2))
  307.         return 1;
  308.     for (k = 0; k < 8; k++)    {
  309.         if (!isxdigit (str[k]))
  310.             return 0;
  311.     }
  312.     return 1;
  313. }
  314.  
  315.  
  316. /* Set interface IP address */
  317. static int
  318. ifipaddr (int argc OPTIONAL, char *argv[], void *p)
  319. {
  320. struct iface *ifp = p;
  321.  
  322.     /* Do not allow loopback iface to be changed ! - WG7J */
  323.     if (ifp == &Loopback) {
  324.         tputs (nochangeIP);
  325.         return 0;
  326.     }
  327.     ifp->addr = (ishexaddr (argv[1])) ? (uint32) htol (argv[1]) : resolve (argv[1]);
  328.     return 0;
  329. }
  330.  
  331.  
  332.  
  333. /* Set IP call sign */
  334. static int
  335. ifipcall (int argc OPTIONAL, char *argv[], void *p)
  336. {
  337. struct iface *ifp = p;
  338.  
  339.     if (ifp->iftype == NULLIFT || ifp->iftype->scan == NULL) {
  340.         tputs (setIPcall);
  341.         return 1;
  342.     }
  343.     if (ifp->ipcall != NULLCHAR)
  344.         free (ifp->ipcall);
  345.     ifp->ipcall = mallocw ((unsigned) ifp->iftype->hwalen);
  346.     (void) (*ifp->iftype->scan) (ifp->ipcall, argv[1]);
  347.     return 0;
  348. }
  349.  
  350.  
  351.  
  352. /* Set link (hardware) address */
  353. static int
  354. iflinkadr (int argc OPTIONAL, char *argv[], void *p)
  355. {
  356. struct iface *ifp = p;
  357.  
  358.     if (ifp->iftype == NULLIFT || ifp->iftype->scan == NULL) {
  359.         tputs (setlinkaddr);
  360.         return 1;
  361.     }
  362.     if (ifp->hwaddr != NULLCHAR)
  363.         free (ifp->hwaddr);
  364.     ifp->hwaddr = mallocw ((unsigned) ifp->iftype->hwalen);
  365.     (void) (*ifp->iftype->scan) (ifp->hwaddr, argv[1]);
  366. #if defined(MAILBOX) && defined(NETROM)
  367.     if (ifp == Nr_iface)    /*the netrom call just got changed! - WG7J*/
  368.         setmbnrid ();
  369. #endif
  370.     return 0;
  371. }
  372.  
  373.  
  374.  
  375. /* Set interface broadcast address. This is actually done
  376.  * by installing a private entry in the routing table.
  377.  */
  378. static int
  379. ifbroad (int argc OPTIONAL, char *argv[], void *p)
  380. {
  381. struct iface *ifp = p;
  382. struct route *rp;
  383.  
  384.     rp = rt_blookup (ifp->broadcast, 32);
  385.     if (rp != NULLROUTE && rp->iface == ifp)
  386.         (void) rt_drop (ifp->broadcast, 32);
  387.  
  388.     ifp->broadcast = (ishexaddr (argv[1])) ? (uint32) htol (argv[1]): resolve (argv[1]);
  389.     (void) rt_add (ifp->broadcast, 32, 0L, ifp, 1L, 0L, 1);
  390.     return 0;
  391. }
  392.  
  393.  
  394.  
  395. /* Set the network mask. This is actually done by installing
  396.  * a routing entry.
  397.  */
  398. static int
  399. ifnetmsk (int argc OPTIONAL, char *argv[], void *p)
  400. {
  401. struct iface *ifp = p;
  402. struct route *rp;
  403.  
  404.     /* Remove old entry if it exists */
  405.     rp = rt_blookup (ifp->addr & ifp->netmask, (unsigned) mask2width (ifp->netmask));
  406.     if (rp != NULLROUTE)
  407.         (void) rt_drop (rp->target, rp->bits);
  408.  
  409.     ifp->netmask = (ishexaddr (argv[1])) ? (uint32) htol (argv[1]) : resolve (argv[1]);
  410.     (void) rt_add (ifp->addr, (unsigned) mask2width (ifp->netmask), 0L, ifp, 0L, 0L, 0);
  411.     return 0;
  412. }
  413.  
  414.  
  415.  
  416. /* Command to set interface encapsulation mode */
  417. static int
  418. ifencap (int argc OPTIONAL, char *argv[], void *p)
  419. {
  420. struct iface *ifp = p;
  421.  
  422.     if (setencap (ifp, argv[1]) != 0) {
  423.         tprintf (encaperr, argv[1]);
  424.         return 1;
  425.     }
  426.     return 0;
  427. }
  428.  
  429.  
  430.  
  431. /* Function to set encapsulation mode */
  432. int
  433. setencap (struct iface *ifp, const char *mode)
  434. {
  435. struct iftype *ift = (struct iftype *) 0;
  436.  
  437.     if (mode != NULL) {
  438.         /* Configure the whole interface */
  439.         for (ift = &Iftypes[0]; ift->name != NULLCHAR; ift++)
  440.             if (strnicmp (ift->name, mode, strlen (mode)) == 0)
  441.                 break;
  442.         if (ift->name == NULLCHAR)
  443.             return -1;
  444.  
  445.         ifp->iftype = ift;
  446.         ifp->send = ift->send;
  447.         ifp->output = ift->output;
  448.         ifp->type = ift->type;
  449.     }
  450.     /* Set the tcp and ax25 interface parameters */
  451.     if (!ifp->tcp)
  452.         ifp->tcp = callocw (1, sizeof (struct iftcp));
  453.  
  454.     init_iftcp (ifp->tcp);
  455. #ifdef AX25
  456.     if (ift && ift->type == CL_AX25) {
  457.         if (!ifp->ax25)
  458.             ifp->ax25 = callocw (1, sizeof (struct ifax25));
  459.  
  460.         init_ifax25 (ifp->ax25);
  461.         ifp->flags |= AX25_BEACON + MAIL_BEACON + AX25_DIGI + LOG_AXHEARD + LOG_IPHEARD;
  462.     }
  463. #endif
  464.     return 0;
  465. }
  466.  
  467.  
  468.  
  469. #ifdef RXECHO
  470. /* Set interface IP address */
  471. static int
  472. ifrxecho (int argc OPTIONAL, char *argv[], void *p)
  473. {
  474. struct iface *ifp = p;
  475. struct iface *rxecho;
  476.  
  477.     if (!stricmp ("off", argv[1])) {
  478.         ifp->rxecho = NULLIF;
  479.         return 0;
  480.     };
  481.     if ((rxecho = if_lookup (argv[1])) == NULL) {
  482.         tprintf (Badinterface, argv[1]);
  483.         return 0;
  484.     };
  485.     if (ifp->type != rxecho->type) {
  486.         tprintf (notsametype, argv[1]);
  487.         return 0;
  488.     };
  489.     ifp->rxecho = rxecho;
  490.     return 0;
  491. }
  492. #endif /* RXECHO */
  493.  
  494.  
  495.  
  496. /* Set interface Maximum Transmission Unit */
  497. static int
  498. ifmtu (int argc OPTIONAL, char *argv[], void *p)
  499. {
  500. struct iface *ifp = p;
  501.  
  502.     ifp->mtu = (int16) atoi (argv[1]);
  503. #ifdef NETROM
  504.     /* Make sure NETROM mtu <= 236 ! - WG7J */
  505.     if (ifp == Nr_iface)
  506.         if (Nr_iface->mtu > NR4MAXINFO)
  507.             Nr_iface->mtu = NR4MAXINFO;
  508. #endif
  509.     return 0;
  510. }
  511.  
  512.  
  513.  
  514. /* Set interface metric for RIP -  */
  515. static int
  516. ifmetric (int argc OPTIONAL, char *argv[], void *p)
  517. {
  518. struct iface *ifp = p;
  519.  
  520.     ifp->iface_metric = atoi (argv[1]);
  521.     return 0;
  522. }
  523.  
  524.  
  525.  
  526. /* Set interface forwarding */
  527. static int
  528. ifforw (int argc OPTIONAL, char *argv[], void *p)
  529. {
  530. struct iface *ifp = p;
  531.  
  532.     ifp->forw = if_lookup (argv[1]);
  533.     if (ifp->forw == ifp)
  534.         ifp->forw = NULLIF;
  535.     return 0;
  536. }
  537.  
  538.  
  539.  
  540. /*give a little description for each interface - WG7J*/
  541. static int
  542. ifdescr (int argc OPTIONAL, char *argv[], void *p)
  543. {
  544. struct iface *ifp = p;
  545.  
  546. #ifdef NETROM
  547. #ifdef ENCAP
  548.     if ((ifp == &Loopback) || (ifp == &Encap) || (ifp == Nr_iface))
  549. #else
  550.     if ((ifp == &Loopback) || (ifp == Nr_iface))
  551. #endif /*ENCAP*/
  552. #else /*NETROM*/
  553. #ifdef ENCAP
  554.     if ((ifp == &Loopback) || (ifp == &Encap))
  555. #else
  556.     if (ifp == &Loopback)
  557. #endif /*ENCAP*/
  558. #endif /*NETROM*/
  559.         return 0;
  560.  
  561.     if (ifp->descr != NULLCHAR) {
  562.         free (ifp->descr);
  563.         ifp->descr = NULLCHAR;    /* reset the pointer */
  564.     }
  565.     if (!strlen (argv[1]))
  566.         return 0;    /* clearing the buffer */
  567.  
  568.     ifp->descr = mallocw (strlen (argv[1]) + 2);    /* allow for the EOL char etc */
  569.     strcpy (ifp->descr, argv[1]);
  570.     strcat (ifp->descr, "\n");    /* add the EOL char */
  571.  
  572.     return 0;
  573. }
  574.  
  575.  
  576.  
  577. /* Display the parameters for a specified interface */
  578. static void
  579. showiface (register struct iface *ifp)
  580. {
  581. char tmp[25];
  582.  
  583.     tprintf (showfmt, ifp->name, inet_ntoa (ifp->addr), (int) ifp->mtu, ifp->iface_metric);
  584.     if (ifp->iftype == NULLIFT)
  585.         tputs (notset);
  586.     else {
  587.         tprintf ("%s%s\n", ifp->iftype->name, (ifp->rmtaddr != NULLCHAR) ? " (AXIP)" : "");
  588.         if (ifp->iftype->format != NULL && ifp->hwaddr != NULLCHAR) {
  589.             tprintf (showlink, (*ifp->iftype->format) (tmp, ifp->hwaddr));
  590. #ifdef AX25
  591.             if (ifp->iftype->type == CL_AX25) {
  592.                 if (ifp->ipcall != NULLCHAR)
  593.                     tprintf (showIPcall, (*ifp->iftype->format) (tmp, ifp->ipcall));
  594.                 tprintf (showlenirtt, (int) ifp->ax25->paclen, ifp->ax25->irtt);
  595.                 if (ifp->ax25->bctext)
  596.                     tprintf (showbctext, ifp->ax25->bctext);
  597.                 if (ifp->rmtaddr != NULLCHAR) {
  598.                     tprintf (showremote, (*ifp->iftype->format) (tmp, ifp->rmtaddr));
  599. #ifdef AXIP
  600.                     tprintf (showremoteIP, inet_ntoa (axipaddr[ifp->dev]));
  601. #endif
  602.                 }
  603.             }
  604. #ifdef NETROM
  605.             else if (ifp == Nr_iface)
  606.                 tprintf ("   Alias %s\n", Nralias);
  607. #endif
  608.             else
  609. #endif
  610.                 tputc ('\n');
  611.         }
  612.     }
  613.     tprintf (showflags, ifp->flags, ifp->trace, ifp->netmask, inet_ntoa (ifp->broadcast));
  614.     if (ifp->forw != NULLIF)
  615.         tprintf (showforw, ifp->forw->name);
  616. #ifdef RXECHO
  617.     if (ifp->rxecho != NULLIF)
  618.         tprintf (showrxecho, ifp->rxecho->name);
  619. #endif
  620.     tprintf (showsent, ifp->ipsndcnt, ifp->rawsndcnt, tformat (secclock () - ifp->lastsent));
  621.     tprintf (showrecv, ifp->iprecvcnt, ifp->rawrecvcnt, tformat (secclock () - ifp->lastrecv));
  622.     if (ifp->descr != NULLCHAR)
  623.         tprintf (showdescr, ifp->descr);
  624. }
  625.  
  626.  
  627.  
  628. /* Command to detach an interface */
  629. int
  630. dodetach (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
  631. {
  632. register struct iface *ifp;
  633.  
  634.     if ((ifp = if_lookup (argv[1])) == NULLIF) {
  635.         tprintf (Badinterface, argv[1]);
  636.         return 1;
  637.     }
  638.     if (if_detach (ifp) == -1)
  639.         tputs (detnope);
  640.     return 0;
  641. }
  642.  
  643.  
  644.  
  645. /* Detach a specified interface */
  646. int
  647. if_detach (register struct iface *ifp)
  648. {
  649. struct iface *iftmp;
  650. struct route *rp, *rptmp;
  651. int i, j;
  652. struct ax_route *axr, *axr1;
  653. struct arp_tab *ap, *ap1;
  654.  
  655. #ifdef ENCAP
  656.     if (ifp == &Loopback || ifp == &Encap)
  657. #else
  658.     if (ifp == &Loopback)
  659. #endif
  660.         return -1;
  661.  
  662. #ifdef AX25
  663.     /* Drop all ax25 routes that points to this interface */
  664.     for (axr = Ax_routes; axr != NULLAXR; axr = axr1) {
  665.         axr1 = axr->next;    /* Save the next pointer */
  666.         if (axr->iface == ifp)
  667.             (void) ax_drop (axr->target, ifp, AX_NONSETUP);
  668.         /* axr will be undefined after ax_drop() */
  669.     }
  670. #endif
  671.  
  672.     /* Drop all ARP's that point to this interface */
  673.     for (i = 0; i < HASHMOD; ++i)
  674.         for (ap = Arp_tab[i]; ap != NULLARP; ap = ap1) {
  675.             ap1 = ap->next;    /* Save the next pointer */
  676.             if (ap->iface == ifp)
  677.                 arp_drop (ap);
  678.             /* ap will be undefined after arp_drop() */
  679.         }
  680.  
  681.  
  682.     /* Drop all routes that point to this interface */
  683.     if (R_default.iface == ifp)
  684.         (void) rt_drop (0L, 0);/* Drop default route */
  685.  
  686.     for (i = 0; i < HASHMOD; i++) {
  687.         for (j = 0; j < 32; j++) {
  688.             for (rp = Routes[j][i]; rp != NULLROUTE; rp = rptmp) {
  689.                 /* Save next pointer in case we delete this entry */
  690.                 rptmp = rp->next;
  691.                 if (rp->iface == ifp)
  692.                     (void) rt_drop (rp->target, rp->bits);
  693.             }
  694.         }
  695.     }
  696.     /* Unforward any other interfaces forwarding to this one */
  697.     for (iftmp = Ifaces; iftmp != NULLIF; iftmp = iftmp->next) {
  698.         if (iftmp->forw == ifp)
  699.             iftmp->forw = NULLIF;
  700. #ifdef RXECHO
  701.         if (iftmp->rxecho == ifp)
  702.             iftmp->rxecho = NULLIF;
  703. #endif
  704.     }
  705.  
  706.     /* Call device shutdown routine, if any */
  707.     if (ifp->stop != NULLFP ((struct iface *)))
  708.         (void) (*ifp->stop) (ifp);
  709.  
  710.     killproc (ifp->rxproc);
  711.     killproc (ifp->txproc);
  712.     killproc (ifp->supv);
  713.  
  714. #ifdef NETROM
  715.     /*make sure that the netrom interface is properly detached
  716.      *fixed 11/15/91, Johan. K. Reinalda, WG7J/PA3DIS
  717.      */
  718.     if (strcmp (ifp->name, "netrom") == 0) {
  719.         for (iftmp = Ifaces; iftmp; iftmp = iftmp->next)
  720.             iftmp->flags &= ~IS_NR_IFACE;    /* this 'resets' active interfaces */
  721.         Nr_iface = NULLIF;
  722.     }
  723. #endif
  724.  
  725.     /* Free allocated memory associated with this interface */
  726.     if (ifp->name != NULLCHAR)
  727.         free (ifp->name);
  728.     if (ifp->hwaddr != NULLCHAR)
  729.         free (ifp->hwaddr);
  730.     if (ifp->ipcall != NULLCHAR)
  731.         free (ifp->ipcall);
  732.     free (ifp->tcp);
  733. #ifdef AX25
  734.     if (ifp->ax25) {
  735.         if (ifp->ax25->bctext)
  736.             free (ifp->ax25->bctext);
  737.         free (ifp->ax25);
  738.     }
  739. #endif
  740.     free (ifp->descr);
  741.  
  742.     /* Remove from interface list */
  743.     if (ifp == Ifaces)
  744.         Ifaces = ifp->next;
  745.     else {
  746.         /* Search for entry just before this one
  747.          * (necessary because list is only singly-linked.)
  748.          */
  749.         for (iftmp = Ifaces; iftmp != NULLIF; iftmp = iftmp->next)
  750.             if (iftmp->next == ifp)
  751.                 break;
  752.         if (iftmp != NULLIF && iftmp->next == ifp)
  753.             iftmp->next = ifp->next;
  754.     }
  755.     /* Finally free the structure itself */
  756.     free ((char *) ifp);
  757.     return 0;
  758. }
  759.  
  760.  
  761.  
  762. /* Given the ascii name of an interface, return a pointer to the structure,
  763.  * or NULLIF if it doesn't exist
  764.  */
  765. struct iface *
  766. if_lookup (const char *name)
  767. {
  768. register struct iface *ifp;
  769.  
  770.     for (ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  771.         if (stricmp (ifp->name, name) == 0)
  772.             break;
  773.     return ifp;
  774. }
  775.  
  776.  
  777.  
  778. /* Return iface pointer if 'addr' belongs to one of our interfaces,
  779.  * NULLIF otherwise.
  780.  * This is used to tell if an incoming IP datagram is for us, or if it
  781.  * has to be routed.
  782.  */
  783. struct iface *
  784. ismyaddr (uint32 addr)
  785. {
  786. register struct iface *ifp;
  787.  
  788.     for (ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  789.         if (addr == ifp->addr)
  790.             break;
  791.     return ifp;
  792. }
  793.  
  794.  
  795.  
  796. /* Given a network mask, return the number of contiguous 1-bits starting
  797.  * from the most significant bit.
  798.  */
  799. int
  800. mask2width (uint32 mask)
  801. {
  802. int width, i;
  803.  
  804.     width = 0;
  805.     for (i = 31; i >= 0; i--) {
  806.         if (!(mask & (1L << i)))
  807.             break;
  808.         width++;
  809.     }
  810.     return width;
  811. }
  812.  
  813.  
  814.  
  815. /* return buffer with name + comment */
  816. char *
  817. if_name (struct iface *ifp, const char *comment)
  818. {
  819. char *result = mallocw (strlen (ifp->name) + strlen (comment) + 1);
  820.  
  821.     strcpy (result, ifp->name);
  822.     return strcat (result, comment);
  823. }
  824.  
  825.  
  826.  
  827. /* Raw output routine that tosses all packets. Used by dialer, tip, etc */
  828. int
  829. bitbucket (struct iface *ifp OPTIONAL, struct mbuf *bp)
  830. {
  831.     free_p (bp);
  832.     return 0;
  833. }
  834.  
  835.  
  836.  
  837. /* Set interface (or AX25) flags on 1 or all interfaces */
  838. int
  839. dosetflag (int argc, char *argv[], void *p OPTIONAL, int flagtoset, int AX25only)
  840. {
  841. struct iface *ifp;
  842.  
  843.     if (argc < 2) {
  844.         for (ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  845.             if (ifp->flags & flagtoset)
  846.                 tprintf ("%s\n", ifp->name);
  847.     } else {
  848.         if ((argc == 3) && (strcmp (argv[1], "all") == 0)) {
  849.             for (ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  850.                 if (!AX25only || ifp->type == CL_AX25) {
  851.                     if (strcmp (argv[2], "on") == 0)
  852.                         ifp->flags |= flagtoset;
  853.                     else if (strcmp (argv[2], "off") == 0)
  854.                         ifp->flags &= ~flagtoset;    /*lint !e502 */
  855.                     else {
  856.                         tputs ("Please use on or off.\n");
  857.                         return 0;
  858.                     }
  859.                 }
  860.             return 0;
  861.         } else if ((ifp = if_lookup (argv[1])) == NULLIF) {
  862.             tprintf (Badinterface, argv[1]);
  863.             return 1;
  864.         }
  865.         if (AX25only && ifp->type != CL_AX25) {
  866.             tputs ("not an AX.25 interface\n");
  867.             return -1;
  868.         }
  869.         if (argc != 3)
  870.             ifp->flags ^= flagtoset;
  871.         else {
  872.             if (strcmp (argv[2], "on") == 0)
  873.                 ifp->flags |= flagtoset;
  874.             else if (strcmp (argv[2], "off") == 0)
  875.                 ifp->flags &= ~flagtoset;    /*lint !e502 */
  876.             else
  877.                 ifp->flags ^= flagtoset;
  878.         }
  879.     }
  880.     return 0;
  881. }
  882.  
  883.  
  884. /* attach a dummy interface.  no parms for now. */
  885. int
  886. dummy_attach (argc, argv, p)
  887. int argc OPTIONAL;
  888. char *argv[] OPTIONAL;
  889. void *p OPTIONAL;
  890. {
  891. struct iface *dummy;
  892. uint32 n;
  893.  
  894.     if ((n = resolve (argv[2])) == 0) {
  895.         tprintf (Badhost, argv[2]);
  896.         return 1;
  897.     }
  898.  
  899.     dummy = (struct iface *) callocw (1, sizeof (struct iface));
  900.  
  901.     dummy->addr = n;
  902.     dummy->iface_metric = 1;
  903.  
  904.     /* The strdup is needed to keep the detach routine happy (it'll
  905.      * free the allocated memory)
  906.      */
  907.     dummy->name = strdup (argv[1]);
  908.     dummy->hwaddr = mallocw (AXALEN);
  909.     memcpy (dummy->hwaddr, Mycall, AXALEN);
  910.  
  911.     dummy->mtu = MAXINT16;
  912.     (void) setencap (dummy, "None");
  913.     dummy->next = Ifaces;
  914.     Ifaces = dummy;
  915.  
  916.     return 0;
  917. }
  918.  
  919.  
  920.  
  921.